<template>
	<div>
		<transition name="el-fade-in-linear">
			<!-- <div :id="refId" class="drag-box" ref="dragBox" v-if="isShow"> -->
			<div :id="refId" class="drag-box" ref="dragBox">
				<div
					v-drag="{
						refId,
						isMobile: isMobile
					}"
					ref="dragIcon"
					class="flex flex-justify-center flex-align-center dragIcon"
					:class="{ bounce }"
					@touchstart.stop="onTouchStart"
					@touchmove.prevent.stop="onTouchMove($event)"
					@touchend.stop="onTouchEnd"
					@click="onClick"
					:style="{
						position: isMobile ? 'fixed' : 'absolute',
						left: left + 'px',
						top: top + 'px',
						width: width + 'px',
						height: height + 'px',
						backgroundColor: backgroundColor
					}"
				>
					<slot />
				</div>
			</div>
		</transition>
	</div>
</template>

<script>
import { uuid } from '@/utils'
import { isMobile as isMobileStatus } from "@/utils/validate";
const { clientWidth, clientHeight } = document.documentElement
export default {
	name: 'cl-float-ball',
	directives: {
		drag(el, bind) {
			const oDiv = el
			const { refId, isMobile } = bind.value
			// 拖拽时间标识
			let firstTime = ''
			let lastTime = ''
			document.onselectstart = function () {
				return true
			}
			oDiv.onmousedown = function (e) {
				if (isMobile) return
				// 为了区分点击还是拖拽，使用时间差来判断，200毫秒内为点击，200毫秒外为拖拽，初始化为点击
				document.getElementById(refId).setAttribute('drag-flag', false)
				firstTime = new Date().getTime()

				// oDiv.offsetParent.offsetWidth - oDiv.offsetLeft - oDiv.offsetWidth
				// 表示元素距离父元素右边距的距离
				const disX = oDiv.offsetParent.offsetWidth - oDiv.offsetLeft - oDiv.offsetWidth + e.clientX
				// oDiv.offsetTop 表示距离父元素顶边距的距离
				const disY = oDiv.offsetTop - e.clientY
				// 设置最大右边距
				const maxRight = oDiv.offsetParent.offsetWidth - oDiv.offsetWidth
				// 设置最大顶边距
				const maxTop = oDiv.offsetParent.offsetHeight - oDiv.offsetHeight
				document.onmousemove = function (e) {
					// 计算当前右边距并设置
					const r = Math.min(maxRight, Math.max(disX - e.clientX, 0))
					oDiv.style.right = r + 'px'
					oDiv.style.left = 'auto'
					// 计算当前顶边距并设置
					const t = Math.min(maxTop, Math.max(disY + e.clientY, 0))
					oDiv.style.top = t + 'px'

					// 判断下当前时间与初始时间差，大于200毫秒则判断状态为拖拽
					lastTime = new Date().getTime()
					if (lastTime - firstTime > 200) {
						document.getElementById(refId).setAttribute('drag-flag', true)
					}
				}
				// 鼠标抬起时清除事件
				document.onmouseup = function (e) {
					document.onmousemove = null
					document.onmouseup = null
				}
				return false
			}
		},
	},
	props: {
		width: {
			type: Number,
			default: 60,
		},
		height: {
			type: Number,
			default: 220,
		},
		//视口宽
		clientWidth: {
			type: Number,
			default: clientWidth,
		},
		//视口高
		clientHeight: {
			type: Number,
			default: clientHeight,
		},
		offsetX: {
			type: Number,
			default: 15,
		},
		offsetY: {
			type: Number,
			default: 15,
		},
		bounce: {
			type: Boolean,
			default: false,
		},
		backgroundColor: {
			type: String,
			default: 'transparent',
		},
		borderColor: {
			type: String,
			default: 'transparent',
		},
	},
	data() {
		return {
			refId: uuid(),
			left: 0,
			top: 0,
			startToMove: false,
			isShow: true,
			timer: null,
			currentTop: null,
            isMobile: isMobileStatus
		}
	},
	created() {
		const { offsetX, offsetY } = this
		this.left = this.clientWidth - this.width - offsetX
		this.top = clientHeight - this.height - offsetY
	},
	mounted() {
		this.bindScrollEvent()
		document.onselectstart = function () {
			return true
		}
		// 记得销毁一些全局的的事件
		this.$once('hook:beforeDestroy', () => {
			this.removeScrollEvent()
		})
	},
	methods: {
		onClick(e) {
			// 点击事件触发时，判断当前状态是拖拽还是点击，若是拖拽，直接返回不继续执行
			const isDrag = document.getElementById(this.refId).getAttribute('drag-flag')
			if (isDrag == 'true') {
				return
			}
			this.$emit('click', e)
		},
		onTouchStart() {
			this.startToMove = true
			this.$refs.dragIcon.style.transition = 'none'
		},
		onTouchMove(e) {
			const clientX = e.targetTouches[0].clientX //手指相对视口的x
			const clientY = e.targetTouches[0].clientY //手指相对视口的y
			const isInScreen = clientX <= clientWidth && clientX >= 0 && clientY <= clientHeight && clientY >= 0
			if (this.startToMove && e.targetTouches.length === 1) {
				if (isInScreen) {
					this.left = clientX - this.width / 2
					this.top = clientY - this.height / 2
				}
			}
		},
		onTouchEnd() {
			if (this.left < this.clientWidth / 2) {
				this.left = 15 //不让贴边 所以设置15没设置0
				this.onIconY()
			} else {
				this.left = this.clientWidth - this.width - 15 //不让贴边 所以减15
				this.onIconY()
			}
			this.$refs.dragIcon.style.transition = 'all .3s'
		},
		onIconY() {
			if (this.top < 0) {
				this.top = clientHeight - this.clientHeight + 15 //不上帖上边所以设置为15 没设置0
			} else if (this.top + this.height > this.clientHeight) {
				this.top = clientHeight - this.height - 15 //不让帖下边所以减15
			}
		},
		bindScrollEvent() {
			window.addEventListener('scroll', this.onScrollStart)
		},
		removeScrollEvent() {
			window.removeEventListener('scroll', this.onScrollStart)
		},
		onScrollStart() {
			this.isShow = false
			this.timer && clearTimeout(this.timer)
			this.timer = setTimeout(() => {
				this.onScrollEnd()
			}, 300)
			this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
		},
		onScrollEnd() {
			this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop
			// 判断是否停止滚动的条件
			if (this.scrollTop == this.currentTop) {
				this.isShow = true
			}
		},
	},
}
</script>

<style lang="scss" scoped>
.drag-box {
	z-index: 996;
}
.dragIcon {
	// position: fixed;
	z-index: 2001;
	width: 60px;
	height: 60px;
	border-radius: 50%;
	// background-color: $primary;
	// border-style: solid;
	// border-width: 1px;
	box-sizing: border-box;
	text-align: center;
	// color: #fff;
	cursor: pointer;
	// &.bounce {
	// 	animation: ani-bounce 1s linear infinite alternate;
	// }
}
// @keyframes ani-bounce {
// 	from {
// 		transform: translateY(0);
// 	}
// 	to {
// 		transform: translateY(-20px);
// 	}
// }
.v-enter {
	opacity: 1;
}
.v-leave-to {
	opacity: 0;
}
.v-enter-active,
.v-leave-active {
	transition: opacity 0.3s;
}
</style>
